<link rel="ractive" href="./shared/header.html" name="Header">

<Header app="{{app}}" query="{{query}}"></Header>

<div class="statistics" style="{{#if !stats.lastUpdate}}background-color: #fff;{{/if}}">
	<div class="container">
		{{#if !stats.lastUpdate}}
			<div class="text-center">
				<h2>Loading...</h2>
			</div>
		{{else}}
			<div class="row">
				<div class="col-xs-12 col-xs-offset-6">
					<h1 class="text-center">
						TOTAL CDN STATS<br>
						<small class="text-center">(last 30 days)</small>
					</h1>
				</div>

				<div class="col-xs-5">
					<div class="stats-subtitle stats-last-update">
						Last update: {{formatDate(stats.lastUpdate)}}
					</div>
				</div>
			</div>

			<div class="row">
				<div class="col-md-7 col-md-offset-1 col-sm-7 col-sm-offset-1 col-xs-10 col-xs-offset-2 xs-padding">
					<div class="stats-box">
						<div class="stats-title">LOAD BALANCING DECISIONS</div>
						<div class="stats-number">{{formatNumber(stats.cedexis.total)}}</div>
					</div>
				</div>

				<div class="col-md-6 col-md-offset-1 col-sm-8 col-sm-offset-0 col-xs-10 col-xs-offset-1 xs-padding">
					<div class="stats-box">
						<div class="stats-title">HTTP HITS</div>
						<div class="stats-number">{{formatNumber(stats.cdn.total.hits)}}</div>
						<div class="stats-traffic"><span class="stats-number">{{Math.floor(stats.cdn.total.traffic / 1024 / 1024 / 1024 / 1024)}}TB</span> SERVED</div>
					</div>
				</div>

				<div class="col-md-7 col-md-offset-1 col-sm-7 col-sm-offset-0 col-xs-11 col-xs-offset-7">
					<div class="stats-box">
						<div class="stats-title">DNS REQUESTS</div>
						<div class="stats-number">{{formatNumber(stats.dns.total)}}</div>
					</div>
				</div>
			</div>

			<div class="row">
				<div class="col-md-14 col-md-offset-5 col-xs-22 col-xs-offset-1">
					<h3>Load Balancing decisions</h3>

					<div id="load-balancing"></div>
				</div>

				<div class="col-md-14 col-md-offset-5 col-xs-22 col-xs-offset-1">
					<h3>DNS requests</h3>

					<div id="dns-requests"></div>
				</div>
			</div>

			<div class="row">
				<div class="col-md-14 col-md-offset-5 col-xs-22 col-xs-offset-1">
					<h3>Load Balancing decisions map</h3>

					<div id="load-balancing-map"></div>
				</div>
			</div>

			<div class="row">
				<div class="col-md-14 col-md-offset-5 col-xs-22 col-xs-offset-1">
					<h3>
						Performance map
						<span class="stats-subtitle">Based on tens of millions of RUM tests for the last 24 hours</span>
					</h3>

					<div id="performance-map"></div>
				</div>
			</div>
		{{/if !stats}}
	</div>
</div>

<script type="text/javascript">
	var debounce = require('public/js/utils/debounce');
	var loading = 3;
	var stats;

	component.exports = {
		data: function () {
			return {
				title: 'Statistics - jsDelivr',
				stats: stats,
				formatDate: formatDate,
				formatNumber: formatNumber,
			};
		},
		oninit: function () {
			if (!Ractive.isServer) {
				var _this = this;

				google.load('visualization', '1.1', {
					packages: [ 'corechart', 'geochart' ],
					language: 'en',
					callback: onLoad,
				});

				if (!stats) {
					$.getJSON('/api/stats', function (data) {
						stats = data;

						// Convert UNIX timestamps to Date objects.
						stats.cedexis.decisions.forEach(function (entry) {
							entry[0] = new Date(entry[0] * 1000);
						});

						stats.dns.chart.forEach(function (entry) {
							entry[0] = new Date(entry[0] * 1000);
						});

						stats.cedexis.map.forEach(function (entry) {
							entry[2] = '<span class="total-hits">' + formatNumber(entry[1]) + '</span><img src="data:image/png;base64,' + entry[2] + '">';
						});

						_this.set('stats', stats);
						onLoad();
					});
				}
			}
		},
		onrender: function () {
			var onResize = debounce(draw);

			$(window).on('resize', onResize);
			this.on('unrender', function () {
				$(window).off('rezize', onResize);
			});

			onLoad();
		},
	};

	function onLoad () {
		if (--loading <= 0) {
			draw()
		}
	}

	function draw () {
		if (loading <= 0) {
			var lineChartDefaults = {
				backgroundColor: {
					stroke: '#cee1e1',
					strokeWidth: 4,
				},
				chartArea: {
					left: 100,
					top: 30,
					height: 350,
					width: '85%',
				},
				colors: [ '#3a46b6', '#920784', '#20a9e9', '#d41800' ],
				curveType: 'function',
				focusTarget: 'category',
				fontName: 'Open Sans',
				fontSize: 13,
				hAxis: {
					format: 'MMM d, y',
					gridlines: {
						color: '#dee2e6',
					},
					title: 'Date',
					titleTextStyle: {
						fontSize: 12,
						bold: true,
						italic: false,
					}
				},
				height: 480,
				legend: {
					position: 'bottom',
				},
				tooltip: {
					isHtml: true,
					trigger: 'both',
					textStyle: {
						color: '#fff',
					}
				},
				vAxis: {
					baseline: 0,
					baselineColor: '#dee2e6',
					format: 'decimal',
					gridlines: {
						color: '#dee2e6',
						count: -1,
					},
				},
				width: '100%',
			};
			var mapChartDefaults = {
				legend: {
					position: 'none',
				},
				tooltip: {
					isHtml: true,
					trigger: 'both',
					textStyle: {
						color: '#fff',
					},
				},
			};
			var numberFormatter = new google.visualization.NumberFormat({ fractionDigits: 0 });
			var perfFormatter = new google.visualization.NumberFormat({ fractionDigits: 0, suffix: ' ms' });

			// Load balancing.
			var loadBalancingData = new google.visualization.DataTable();

			loadBalancingData.addColumn('date', 'Date');
			loadBalancingData.addColumn('number', 'MaxCDN');
			loadBalancingData.addColumn('number', 'CloudFlare');
			loadBalancingData.addColumn('number', 'KeyCDN');
			loadBalancingData.addColumn('number', 'Quantil');
			loadBalancingData.addRows(stats.cedexis.decisions);

			numberFormatter.format(loadBalancingData, 1);
			numberFormatter.format(loadBalancingData, 2);
			numberFormatter.format(loadBalancingData, 3);
			numberFormatter.format(loadBalancingData, 4);

			var loadBalancingChart = new google.visualization.LineChart($('#load-balancing')[0]);
			loadBalancingChart.draw(loadBalancingData, lineChartDefaults);

			// DNS.
			var dnsData = new google.visualization.DataTable();

			dnsData.addColumn('date', 'Date');
			dnsData.addColumn('number', 'Requests');
			dnsData.addRows(stats.dns.chart);

			numberFormatter.format(dnsData, 1);

			var dnsChart = new google.visualization.LineChart($('#dns-requests')[0]);
			dnsChart.draw(dnsData, $.extend(true, {}, lineChartDefaults, {
				chartArea: {
					width: '83%',
				},
				legend: {
					position: 'none',
				},
			}));

			// Load balancing map.
			var mapData = new google.visualization.DataTable();

			mapData.addColumn('string', 'Country');
			mapData.addColumn('number', 'Decisions');
			mapData.addColumn({ type: 'string', role: 'tooltip', p: { html: true } });
			mapData.addRows(stats.cedexis.map);

			numberFormatter.format(mapData, 1);

			var mapChart = new google.visualization.GeoChart($('#load-balancing-map')[0]);
			mapChart.draw(mapData, $.extend(true, {
				colorAxis: {
					colors: [ '#46a3d5', '#a9edd9', '#ffee99', '#f9a674', '#f08c6b', '#dc5559' ],
					maxValue: 60000000,
				},
			}, mapChartDefaults));

			// Performance map.
			var perfMapData = new google.visualization.DataTable();

			perfMapData.addColumn('string', 'Country');
			perfMapData.addColumn('number', 'HTTP load time');
			perfMapData.addRows(stats.cedexis.perfmap);

			perfFormatter.format(perfMapData, 1);

			var perfMapChart = new google.visualization.GeoChart($('#performance-map')[0]);
			perfMapChart.draw(perfMapData, $.extend(true, {
				colorAxis: {
					colors: [ '#46a3d5', '#a9edd9', '#ffee99', '#f9a674', '#f08c6b', '#dc5559' ],
					maxValue: 200,
				},
			}, mapChartDefaults));
		}
	}

	function formatDate (date) {
		return new Date(date).toLocaleString('en', {
			hour12: false,
			month: 'short',
			day: 'numeric',
			year: 'numeric',
			hour: 'numeric',
			minute: 'numeric',
		});
	}

	function formatNumber (number) {
		return number.toString().replace(/\d(?=(?:\d{3})+$)/g, '$&,');
	}
</script>
